#include "pr2000_table.h"
#include "pr2000_user_config.h"
#include "pr2000_support.h"

enum _eCameraStandard DEFAULT_CAMERA_STANDARD = HDA;
enum _eCameraResolution DEFAULT_CAMERA_RESOLUTION = video_1280x720p25;
int DEFAULT_AUTODETECT_ENABLE = 1;

//////////////////////////////////////////////////////////////////////////////////////////////
_stAttrChip PR2000_ATTR_CHIP[MAX_PR2000_CHIPCNT] = 
#if 1 //support 148.5Mhz
{/*{{{*/
	//chip 0 // PARALLEL interface
	{ 
		0x5C<<1, //i2c slave address of chip
		1, //unsigned char vinMode; => 1:Single VinP pin, 3:Single VinN pin, 0:Differential VinPN pin.
		0, //unsigned char vidOutMode; => 0:parallel1, 2:mipi csi 2lane(~HD), 4:mipi csi 4lane(~FHD).
		0, //unsigned char bCascade; => 0:no cascade, 1:cascade
		0, //unsigned char bCascadeMux; =>If cascade, 0:single(slave), 1:mux(master). if cascade slave, set to 0. nocascade don't care.
		1, //unsigned char chid_num; => If cascade, master:0, slave:1. nocascade don't care.
		1, //unsigned char bBt656; =>If parallel, 0:BT1120(8bit), 1:BT656(8bit). if cascade, set equal to another chip.
		0, //unsigned char datarate; =>datarate 0:148.5Mhz, 1:74.25Mhz, 2:36Mhz, 3:27Mhz. if cascade, set master&slave 0(148.5Mhz) both. if mipi, set 0(148.5Mhz)
		3, //unsigned char clkphase_Mux -> (0~15); =>If parallel & bCascadeMux, clkphase. mipi don't care.
		0, //unsigned char clkphase_148Mhz -> (0~15); =>If parallel & datarate=0, clkphase. mipi don't care.
		0, //unsigned char clkphase_74Mhz -> (0~15); =>If parallel & datarate=1, clkphase. mipi don't care.
		0, //unsigned char clkphase_36Mhz -> (0~3); =>If parallel & datarate=2, clkphase. mipi don't care.
		0 //unsigned char clkphase_27Mhz -> (0~3); =>If parallel & datarate=3, clkphase. mipi don't care.
	}
};/*}}}*/
#else //support 74.25Mhz
{/*{{{*/
	//chip 0 // PARALLEL interface
	{ 
		0x5C<<1, //i2c slave address of chip
		1, //unsigned char vinMode; => 1:Single VinP pin, 3:Single VinN pin, 0:Differential VinPN pin.
		0, //unsigned char vidOutMode; => 0:parallel1, 2:mipi csi 2lane(~HD), 4:mipi csi 4lane(~FHD).
		0, //unsigned char bCascade; => 0:no cascade, 1:cascade
		0, //unsigned char bCascadeMux; =>If cascade, 0:single(slave), 1:mux(master). if cascade slave, set to 0. nocascade don't care.
		1, //unsigned char chid_num; => If cascade, master:0, slave:1. nocascade don't care.
		1, //unsigned char bBt656; =>If parallel, 0:BT1120(8bit), 1:BT656(8bit). if cascade, set equal to another chip.
		1, //unsigned char datarate; =>datarate 0:148.5Mhz, 1:74.25Mhz, 2:36Mhz, 3:27Mhz. if cascade, set master&slave 0(148.5Mhz) both. if mipi, set 0(148.5Mhz)
		3, //unsigned char clkphase_Mux -> (0~15); =>If parallel & bCascadeMux, clkphase. mipi don't care.
		0, //unsigned char clkphase_148Mhz -> (0~15); =>If parallel & datarate=0, clkphase. mipi don't care.
		0, //unsigned char clkphase_74Mhz -> (0~15); =>If parallel & datarate=1, clkphase. mipi don't care.
		0, //unsigned char clkphase_36Mhz -> (0~3); =>If parallel & datarate=2, clkphase. mipi don't care.
		0 //unsigned char clkphase_27Mhz -> (0~3); =>If parallel & datarate=3, clkphase. mipi don't care.
	}
};/*}}}*/
#endif

/* set attribute of gpio pin. reference "datasheet" */ 
const _stAttrGpioPin PR2000_ATTR_GPIOPIN[MAX_PR2000_CHIPCNT] = {
	//chip 0
	{ 
		0x5C<<1, //i2c slave address of chip
		{/*{{{*/
			//gpio0 => IRQ
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				1,           1,           0,       0,            1, 
			},
			//gpio1 => PTZ
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				1,           1,           0,       0,            0, 
			},
			//gpio2 => Field sync
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				0,           0,           0,       2,            0, 
			},
			//gpio3 => V sync
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				0,           0,           0,       1,            0, 
			},
			//gpio4 => H sync
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				0,           0,           0,       0,            0, 
			},
			//gpio5 => SPI MOSI
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				1,           1,           0,       0,            0, 
			},
			//gpio6 => SPI MISO
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				1,           1,           0,       0,            0, 
			},
			//gpio7 => SPI SCLK
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				1,           1,           0,       0,            0, 
			},
			//gpio8 => SPI SS
			{ 
				//gpio_iob, gpio_ext_md, gpio_mpp_md, mpp_sel, gpio0_irq_md
				1,           1,           0,       0,            0, 
			},
		}/*}}}*/
	}
};


//////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(__HOST_LINUX_SYSTEM__)
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <linux/proc_fs.h>

#undef PR2000_IRQ_CPU_EXTERNAL  //If use cpu external irq, define

int SetCPUExternalInterrupt(void)
{
#ifdef PR2000_IRQ_CPU_EXTERNAL  //If use cpu external irq, define
	/* gpio15_02 -> set external interrupt */
#define MUXCTL_PHY_ADDR        		IO_ADDRESS(0x120F0000)           
#define MUXCTL_REG			(MUXCTL_PHY_ADDR + 0x02FC) // 0x2FC[muxctrl_reg191]: sata_led_n1/gpio15_2
#define GPIO_PHY_ADDR            	IO_ADDRESS(0x12240000)
#define GPIOREG				(15) //gpio15_0
#define GPIONUM				(2)  //gpio15_2
#define GPIO_INT_NUM 			(92)	//gpio15 irq number. refer document.

#define GPIO_DATA                     	(GPIO_PHY_ADDR + 0x03FC) 
#define GPIO_DIR                      	(GPIO_PHY_ADDR + 0x0400)
#define GPIO_IS                       	(GPIO_PHY_ADDR + 0x0404)
#define GPIO_IBE                      	(GPIO_PHY_ADDR + 0x0408)
#define GPIO_IEV                      	(GPIO_PHY_ADDR + 0x040C)
#define GPIO_IE                       	(GPIO_PHY_ADDR + 0x0410)
#define GPIO_RIS                      	(GPIO_PHY_ADDR + 0x0414)
#define GPIO_MIS                      	(GPIO_PHY_ADDR + 0x0418)
#define GPIO_IC                       	(GPIO_PHY_ADDR + 0x041C)

	/* Use cpu gpio interrupt handler. */

	__u32 reg = 0;
	int intNum = GPIO_INT_NUM;

	/* gpio mode */
#ifdef MUXCTL_REG
	reg = 0;
	writeb( reg, (volatile void __iomem *)MUXCTL_REG);     
#endif // MUXCTL_REG

	printk("Init: set cpu gpio%d_%d external interrupt. \n", GPIOREG, GPIONUM); //gpio15_2 --> Chip0(Master)
	{/*{{{*/
		/* input mode */
		reg = readb((volatile void __iomem *)GPIO_DIR);
		reg &= (__u32)~(0x1<<(GPIONUM)); /* input mode */
		writeb( reg, (volatile void __iomem *)GPIO_DIR);  /* set input mode */

		/* level sensitive mode */
		reg = readb((volatile void __iomem *)GPIO_IS);
		reg |= (__u32)(0x1<<(GPIONUM)); /* level sensitive mode */
		writeb( reg, (volatile void __iomem *)GPIO_IS);  /* set level sensitive mode */

		/* low-level sensitive mode */
		reg = readb((volatile void __iomem *)GPIO_IEV);
		reg &= (__u32)~(0x1<<(GPIONUM)); /* low-level sensitive mode */
		writeb( reg, (volatile void __iomem *)GPIO_IEV);  /* set low-level sensitive mode */

		/* clear interrupt */
		reg = readb((volatile void __iomem *)GPIO_IC);
		reg |= (__u32)(0x1<<(GPIONUM)); 
		writeb( reg, (volatile void __iomem *)GPIO_IC);  

		/* enable interrupt */
		reg = readb((volatile void __iomem *)GPIO_IE);
		reg |= (__u32)(0x1<<(GPIONUM)); 
		writeb( reg, (volatile void __iomem *)GPIO_IE);  
	}/*}}}*/

	return(intNum);
#else
	/* Don't use cpu gpio interrupt handler. thread polling check. */
	return(0);
#endif
}

#endif //defined(__HOST_LINUX_SYSTEM__)

